/*
 *  minikernel/include/kernel.h
 *
 *  Minikernel. Versi�n 1.0
 *
 *  Fernando P�rez Costoya
 *
 */

/*
 *
 * Fichero de cabecera que contiene definiciones usadas por kernel.c
 *
 *      SE DEBE MODIFICAR PARA INCLUIR NUEVA FUNCIONALIDAD
 *
 */

#ifndef _KERNEL_H
#define _KERNEL_H

#include "const.h"
#include "HAL.h"
#include "llamsis.h"

/*Constantes*/
#define NO_RECURSIVO 0
#define RECURSIVO 1

/*Variables Globales*/
int numero_ticks_global;
int numero_ticks_proceso;
int expulsado_init;
int numero_mutex;
char buffer_teclado [TAM_BUF_TERM];
int numero_caracteres;

/*
 *
 * Definicion del tipo que corresponde con el BCP.
 * Se va a modificar al incluir la funcionalidad pedida.
 *
 */
typedef struct BCP_t *BCPptr;

typedef struct BCP_t {
    int id;				/* ident. del proceso */
    int estado;			/* TERMINADO|LISTO|EJECUCION|BLOQUEADO*/
    contexto_t contexto_regs;	/* copia de regs. de UCP */
    int prioridad;              /* prioridad del proceso*/
    int tick_dormido;           /* tick_dormido*/
    int numero_expulsiones;     /* numero de explusiones involuntario*/
    void * pila;                /* dir. inicial de la pila */
    BCPptr padre;               /* padre del proceso*/
    BCPptr siguiente;		/* puntero a otro BCP */
    void *info_mem;		/* descriptor del mapa de memoria */
    int mutex_abiertos[NUM_MUT];	/* Mutex Abiertos por el proceso*/
} BCP;

/*
 *
 * Definicion del tipo que corresponde con la cabecera de una lista
 * de BCPs. Este tipo se puede usar para diversas listas (procesos listos,
 * procesos bloqueados en sem�foro, etc.).
 *
 */

typedef struct{
    BCP *primero;
    BCP *ultimo;
} lista_BCPs;

typedef struct{
    
    char nombre_mutex[8]; /*nombre del mutext*/
    int estado; /*estado del Mutex LOCK|UNLOCK*/
    int id_mutex; /*Identificador del mutex*/
    int id_proceso_bloqueante; /* id del proceso que bloquea el mutex*/
    int tipo_mutex; /*si es RECURSIVO o NO_RECURSIVO*/
    int num_bloqueos; /*si es RECURSIVO el numero de veces que ha sido bloqueado por el proceso*/
    
} Mutex;


/*
 * Variable global que identifica el proceso actual
 */

BCP * p_proc_actual=NULL;

BCP *ultimo_eje=NULL;
/*
 * Variable global que representa la tabla de procesos
 */

BCP tabla_procs[MAX_PROC];

/*
 * Variable global que representa la tabla de mutex
 */

Mutex tabla_mutex[NUM_MUT];

/*
 * Variable global que representa la cola de procesos listos
 */
lista_BCPs lista_dormidos= {NULL, NULL};

/*
 * Variable global que representa la cola de procesos listos
 */
lista_BCPs lista_alta= {NULL, NULL};

/*
 * Variable global que representa la cola de procesos listos
 */
lista_BCPs lista_media= {NULL, NULL};

/*
 * Variable global que representa la cola de procesos listos
 */
lista_BCPs lista_baja= {NULL, NULL};

/*
 * Variable global que representa la cola de procesos listos
 */
lista_BCPs lista_bloqueados_teclado= {NULL, NULL};

/*
 * Variable global que representa la cola de procesos bloqueados por mutex
 */
lista_BCPs lista_bloqueados_mutex[NUM_MUT];

/*
 *
 * Definici�n del tipo que corresponde con una entrada en la tabla de
 * llamadas al sistema.
 *
 */
typedef struct{
    int (*fservicio)();
} servicio;


/*
 * Prototipos de las rutinas que realizan cada llamada al sistema
 */
int sis_crear_proceso();
int sis_terminar_proceso();
int sis_escribir();
int sis_crear_proceso_prioridad();
int sis_obtener_id();
int sis_obtener_id_padre();
int sis_obtener_numero_expulsiones();
int sis_dormir();
int sis_crear_mutex();
int sis_abrir_mutex();
int sis_lock();
int sis_unlock();
int sis_cerrar_mutex();
int sis_leer_caracter();

/*
 * Variable global que contiene las rutinas que realizan cada llamada
 */
servicio tabla_servicios[NSERVICIOS]={
    {sis_crear_proceso},
    {sis_terminar_proceso},
    {sis_escribir},
    {sis_crear_proceso_prioridad},
    {sis_obtener_id},
    {sis_obtener_id_padre},
    {sis_obtener_numero_expulsiones},
    {sis_dormir},
    {sis_crear_mutex},
    {sis_abrir_mutex},
    {sis_lock},
    {sis_unlock},
    {sis_cerrar_mutex},
    {sis_leer_caracter},
};

/*Funciones auxiliares*/
static BCP * planificador_alto();
static BCP * planificador_medio();
static BCP * planificador_bajo();
BCP* buscar_posicion(lista_BCPs * lista, BCP * proc);
void imprimir_listas();
void imprimir_listas_mutex();
void imprimir_mutex();
lista_BCPs * obtener_lista(BCP * proc);
int comprobar_dormidos();
int buscar_entrada_mutex_libre(char *);
int noHayMasProcesos();
int anyadirMutexAbierto(BCP * proceso, int id);
int comprobarMutexAbierto(BCP * proceso, int id);
int eliminarMutexAbierto(BCP * proceso, int id);
int isMutexExiste(int id);
void inicializarTablaMutex(BCP * proceso);
void inicializarMutex();
void liberarMutexProceso(BCP * proceso);
void liberarMutex(int desc);
void desbloquearProcesoTeclado();
void recolocarBuffer(char * buffer);
#endif /* _KERNEL_H */

